package org.lboot.flow.processor.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lboot.flow.constant.FlowNodeTypeConst;
import org.lboot.flow.constant.FlowWorkStatusEnum;
import org.lboot.flow.event.system.*;
import org.lboot.flow.loader.DecisionMarkerLoader;
import org.lboot.flow.model.node.AutoDecisionModel;
import org.lboot.flow.model.node.BaseModel;
import org.lboot.flow.module.work.FlowWork;
import org.lboot.flow.module.work.FlowWorkService;
import org.lboot.flow.module.work.params.FlowTaskParams;
import org.lboot.flow.processor.FlowNodeProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author kindear
 * 自动决策节点
 */
@Slf4j
@Service
@AllArgsConstructor
public class AutoDecisionNodeProcessor implements FlowNodeProcessor {

    List<DecisionMarkerLoader> decisionMarkers;


    FlowWorkService flowWorkService;

    @Resource
    ApplicationContext context;

    @Override
    public String getNodeType() {
        return FlowNodeTypeConst.AUTO_DECISION_TASK_NODE;
    }

    @Override
    public void process(FlowWork flowWork, FlowTaskParams taskParams) {
        FlowWork oldFlow = new FlowWork();
        BeanUtil.copyProperties(flowWork,oldFlow, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        // 流程执行到下一步
        BaseModel currentNode = flowWork.getCurrentModel();
        // 自动决策节点类型
        AutoDecisionModel model = (AutoDecisionModel) currentNode;
        // 决策结果
        String decisionResult = null;
        for (DecisionMarkerLoader maker:decisionMarkers){
            // 决策器ID
            if (maker.getMaker().equals(model.getDecisionMaker())){
                // 执行决策
                decisionResult = maker.make(flowWork);
                break;
            }
        }
        String flowWorkStatus =  flowWork.getFlowWorkStatus();
        // 获取可选节点范围
        List<String> nodeIds = model.getNodeIds();
        // 可选范围为空 / 未找到决策器 / 结果不在可选范围 --> 直接进入流程阻塞状态
        if (nodeIds.isEmpty() || Validator.isEmpty(decisionResult) || !nodeIds.contains(decisionResult)){
            // 发布流程等待
            if (flowWorkStatus.equals(FlowWorkStatusEnum.IN_PROCESS.value)){
                flowWork.setFlowWorkStatus(FlowWorkStatusEnum.IN_WAIT.value);
                flowWorkService.updateOne(flowWork);
                context.publishEvent(new FlowInWaitEvent(this,flowWork));
            }
        }else {
            BaseModel nextModel = flowWork.getNodeModel(decisionResult);
            flowWork.setCurrentNodeId(nextModel.getId());
            flowWork.setCurrentNodeType(nextModel.getNodeType());
            flowWork.setNextNodeId(nextModel.getNextNodeId());
            // 不同条件触发不同事件
            if (flowWorkStatus.equals(FlowWorkStatusEnum.IN_WAIT.value)){
                flowWork.setFlowWorkStatus(FlowWorkStatusEnum.IN_PROCESS.value);
                flowWorkService.updateOne(flowWork);
                // 发布流程解除等待事件
                context.publishEvent(new FlowOutWaitEvent(this,flowWork));
            }
            // 发布流程流转事件
            context.publishEvent(new FlowProcessEvent(this,oldFlow,flowWork));
        }
    }

    @Override
    public void back(FlowWork flowWork, FlowTaskParams taskParams) {

    }
}
